package com.yunyao.framework.service.impl;

import com.alibaba.fastjson2.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunyao.common.constant.enums.AuditStatusEnums;
import com.yunyao.common.constant.enums.ContractPriceType;
import com.yunyao.common.constant.enums.DataDeletedStatus;
import com.yunyao.common.constant.enums.DateFormatPattern;
import com.yunyao.common.constant.enums.SaleContractType;
import com.yunyao.common.core.BaseContext;
import com.yunyao.common.core.redis.RedisCache;
import com.yunyao.common.dto.SaleContractDto;
import com.yunyao.common.dto.excel.ContractExcelDto;
import com.yunyao.common.dto.excel.ContractMaterialExcelDto;
import com.yunyao.common.web.enums.ResultMsgEnum;
import com.yunyao.common.web.util.ConvertUtil;
import com.yunyao.common.web.util.PageResult;
import com.yunyao.common.web.util.YResult;
import com.yunyao.dao.model.BamuContractMaterial;
import com.yunyao.dao.model.BamuContractWirePay;
import com.yunyao.dao.model.BamuPurchaseContract;
import com.yunyao.dao.model.BamuSaleContract;
import com.yunyao.dao.service.bamu.IBamuContractMaterialService;
import com.yunyao.dao.service.bamu.IBamuContractWirePayService;
import com.yunyao.dao.service.bamu.IBamuPurchaseContractService;
import com.yunyao.dao.service.bamu.IBamuSaleContractService;
import com.yunyao.framework.audit.SaleContractAuditHandle;
import com.yunyao.framework.dto.sale.SaleContractApprovalDto;
import com.yunyao.framework.dto.sale.SaleContractSaveDto;
import com.yunyao.framework.dto.sale.SaleContractSubmitApprovalDto;
import com.yunyao.framework.service.SaleContractService;
import com.yunyao.framework.vo.sale.SaleContractInfoVO;
import com.yunyao.framework.vo.sale.SaleContractPurchaseInfoVO;
import com.yunyao.framework.vo.sale.SaleContractVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.yunyao.common.constant.Constants.CODE_PREFIX;
import static com.yunyao.common.constant.Constants.MINUS;
import static com.yunyao.common.constant.Constants.SALE_CODE_PREFIX_SHORT;

/**
 * @author xingjishuai
 * @date 2024-07-11
 */
@Slf4j
@Service
public class SaleContractServiceImpl implements SaleContractService {
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private SaleContractAuditHandle saleContractAuditHandle;
    @Autowired
    private IBamuSaleContractService ibamuSaleContractService;
    @Autowired
    private IBamuPurchaseContractService iBamuPurchaseContractService;
    @Autowired
    private IBamuContractWirePayService iBamuContractWirePayService;

    @Autowired
    private IBamuContractMaterialService iBamuContractMaterialService;
    /**
     * 根据条件分页查询销售合同列表
     *
     * @param saleContractDto 销售合同查询条件
     * @return 返回分页查询结果，包含销售合同列表和分页信息
     * <p>
     * 说明：本方法通过接收一个查询条件对象（saleContractDto），使用该条件对象构建查询包装器（queryWrapper），
     * 对数据库中的销售合同进行分页查询，并将查询结果转换为指定的返回类型（PageResult<SaleContractVO>）。
     * 如果查询结果为空，则返回一个空的分页结果对象。
     */
    @Override
    public YResult<PageResult<SaleContractVO>> pageList(SaleContractDto saleContractDto) {
        // 检查查询条件对象是否为空，如果为空则抛出异常
        if (saleContractDto == null) {
            throw new IllegalArgumentException("SaleContractDto cannot be null");
        }

        // 构建查询条件
        LambdaQueryWrapper<BamuSaleContract> queryWrapper =
                new LambdaQueryWrapper<BamuSaleContract>()
                .eq(BamuSaleContract::getContractType, saleContractDto.getContractType())
                        .eq(BamuSaleContract::getIsDeleted, DataDeletedStatus.NO.getType())
                        .in(CollectionUtils.isNotEmpty(BaseContext.getProjectList()),BamuSaleContract::getProjectId, BaseContext.getProjectList())
                        .between(StringUtils.isNotBlank(saleContractDto.getBeginDate()) && StringUtils.isNotBlank(saleContractDto.getEndDate()),
                                BamuSaleContract::getSignDate,
                                ConvertUtil.getStartOfDay(safeConvertDate(saleContractDto.getBeginDate())), ConvertUtil.getEndOfDay(safeConvertDate(saleContractDto.getEndDate())))
                        .like(StringUtils.isNotBlank(saleContractDto.getContractNo()), BamuSaleContract::getContractNo, saleContractDto.getContractNo()).like(StringUtils.isNotBlank(saleContractDto.getContractName()), BamuSaleContract::getContractName, saleContractDto.getContractName()).eq(StringUtils.isNotBlank(saleContractDto.getProjectId()), BamuSaleContract::getProjectId, saleContractDto.getProjectId()).like(StringUtils.isNotBlank(saleContractDto.getProjectName()), BamuSaleContract::getProjectName, saleContractDto.getProjectName()).eq(StringUtils.isNotBlank(saleContractDto.getSupplierDeptId()), BamuSaleContract::getSupplierDeptId, saleContractDto.getSupplierDeptId()).like(StringUtils.isNotBlank(saleContractDto.getSupplierDeptName()), BamuSaleContract::getSupplierDeptName, saleContractDto.getSupplierDeptName()).eq(StringUtils.isNotBlank(saleContractDto.getPurchaseDeptId()), BamuSaleContract::getPurchaseDeptId, saleContractDto.getPurchaseDeptId()).like(StringUtils.isNotBlank(saleContractDto.getPurchaseDeptName()), BamuSaleContract::getPurchaseDeptName, saleContractDto.getPurchaseDeptName())
                        .like(StringUtils.isNotBlank(saleContractDto.getProjectDeptName()),
                                BamuSaleContract::getProjectDeptName,
                                saleContractDto.getProjectDeptName())
                        .like(StringUtils.isNotBlank(saleContractDto.getMainContractName()),
                                BamuSaleContract::getMainContractName,
                                saleContractDto.getMainContractName())
                        .like(StringUtils.isNotBlank(saleContractDto.getContractName()),
                                BamuSaleContract::getContractName,
                                saleContractDto.getContractName())
                        .eq(StringUtils.isNotBlank(saleContractDto.getAuditStatus()), BamuSaleContract::getAuditStatus, saleContractDto.getAuditStatus())
                        .eq(StringUtils.isNotBlank(saleContractDto.getBindContractStatus()),
                                BamuSaleContract::getBindContractStatus,
                                saleContractDto.getBindContractStatus())
                        .eq(StringUtils.isNotBlank(saleContractDto.getContractMethod()),
                                BamuSaleContract::getContractMethod,
                                saleContractDto.getContractMethod())
                .orderByDesc(BamuSaleContract::getCreatedAt)
                .orderByDesc(BamuSaleContract::getId);

        // 分页查询
        IPage<BamuSaleContract> saleContractPage = new Page<>(saleContractDto.getPageIndex(),
                saleContractDto.getPageSize());
        saleContractPage = ibamuSaleContractService.page(saleContractPage, queryWrapper);

        // 处理查询结果
        if (CollectionUtils.isEmpty(saleContractPage.getRecords())) {
            return YResult.success(new PageResult<>());
        }

        // 转换为VO对象列表
        List<SaleContractVO> saleContractVOList = daoToVoList(saleContractPage.getRecords());
        //
        // 返回分页结果
        return YResult.success(new PageResult<>(saleContractVOList, saleContractPage.getCurrent()
                , saleContractPage.getSize(), saleContractPage.getPages(),
                saleContractPage.getTotal()));
    }

    // 安全地将字符串转换为日期
    // 该方法旨在处理字符串到日期的转换过程中可能出现的异常
    // 如果转换失败，它不会使整个程序崩溃，而是记录警告并返回null
    // 这提高了代码的健壮性和错误处理能力
    private Date safeConvertDate(String dateString) {
        try {
            // 尝试使用ConvertUtil工具类将字符串转换为日期
            return ConvertUtil.getString2Date(dateString);
        } catch (Exception e) {
            // 如果转换失败，记录警告信息，包括失败的字符串和异常详情
            log.warn("Failed to convert date string: {}", dateString, e);
            // 返回null作为转换失败的指示，或者可以返回一个默认日期
            return null;
        }
    }

    /**
     * 将数据访问对象（DAO）列表转换为视图对象（VO）列表
     * 这个方法主要用于处理销售合同数据，将它们从数据库格式转换为更易于前端展示的格式
     *
     * @param records 销售合同数据访问对象的列表，代表从数据库中查询到的销售合同数据
     * @return 返回一个视图对象列表，包含了转换后的销售合同信息，便于前端展示
     */
    private List<SaleContractVO> daoToVoList(List<BamuSaleContract> records) {
        // 从记录中提取并去重合同ID，用于后续查询与匹配
        List<String> contractIdList =
                records.stream().map(BamuSaleContract::getId).distinct().toList();
        // 初始化一个映射，用于存储合同ID与对应的电汇信息
        Map<String, BamuContractWirePay> contractWirePayMap = new HashMap<>();
        // 当合同ID列表非空时，从服务中获取电汇信息，并将其添加到映射中
        if (CollectionUtils.isNotEmpty(contractIdList)) {
            contractWirePayMap.putAll(iBamuContractWirePayService.mapByContractIdList(contractIdList));
        }
        // 将数据访问对象列表转换为视图对象列表，期间会使用之前准备的电汇信息映射
        return records.stream().map(x -> daoToVo(x, contractWirePayMap)).collect(Collectors.toList());
    }


    /**
     * 将数据访问对象（DAO）层面的销售合同实体转换为视图对象（VO）
     * 此转换包括基本属性的复制以及特定逻辑处理，如审核按钮状态和价格类型描述的设置
     *
     * @param bamuSaleContract   销售合同实体，来源于数据库层面
     * @param contractWirePayMap 合同与付款方式的映射，用于查找特定合同的付款方式详情
     * @return 返回转换后的销售合同视图对象，用于展示给用户
     */
    private SaleContractVO daoToVo(BamuSaleContract bamuSaleContract, Map<String,
            BamuContractWirePay> contractWirePayMap) {
        // 初始化视图对象
        SaleContractVO saleContractVO = new SaleContractVO();
        // 复制基本属性
        BeanUtils.copyProperties(bamuSaleContract, saleContractVO);
        saleContractVO.setCreatedAt(DateUtils.format(bamuSaleContract.getCreatedAt(),
                DateFormatPattern.YEAR_MONTH_DAY_HOUR_MINUTE_SECOND.getPattern()));
        saleContractVO.setSignDate(DateUtils.format(bamuSaleContract.getSignDate(),
                DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        // 获取审核状态
        String auditStatus = saleContractVO.getAuditStatus();
        // 获取流程实例ID
        String processInstanceId = bamuSaleContract.getProcessInstanceId();
        // 获取模型方案信息ID
        String modelSchemeInfoId = bamuSaleContract.getModelSchemeInfoId();
        // 根据审核状态和其他条件设置审核按钮状态
        if (StringUtils.isNotBlank(auditStatus)
                && StringUtils.equals(auditStatus, AuditStatusEnums.AUDIT.getType().toString())
                && StringUtils.isNotBlank(modelSchemeInfoId)
                && StringUtils.isNotBlank(processInstanceId)) {
            saleContractVO.setAuditButton(saleContractAuditHandle.userIsAuditButton(modelSchemeInfoId, processInstanceId));
        }
        // 通过合同ID获取付款方式详情
        BamuContractWirePay contractWirePay =
                contractWirePayMap.get(bamuSaleContract.getId());
        // 如果付款方式详情非空，设置价格类型和价格类型描述
        if (Objects.nonNull(contractWirePay)) {
            saleContractVO.setPriceType(contractWirePay.getPriceType());
            saleContractVO.setPaymentCycle(contractWirePay.getPaymentCycle());
            saleContractVO.setPriceTypeDesc(ContractPriceType.typeOfDesc(Integer.valueOf(contractWirePay.getPriceType())));
        }
        // 返回转换后的视图对象
        return saleContractVO;
    }

    /**
     * 根据ID获取销售合同信息
     * 此方法通过合同ID查询销售合同的详细信息，包括但不限于合同状态、金额等
     *
     * @param id 合同ID，用于定位特定的销售合同
     * @return 包含销售合同信息的YResult对象，如果找不到对应ID的合同，则返回错误结果
     */
    @Override
    public YResult<SaleContractInfoVO> getSaleContractById(String id) {
        // 调用服务方法查询单个销售合同
        BamuSaleContract bamuSaleContract = ibamuSaleContractService.getByIdNoDelete(id);

        // 处理查询结果
        if (Objects.isNull(bamuSaleContract)) {
            // 如果销售合同不存在，返回错误提示信息
            return YResult.error(ResultMsgEnum.NO_DATA);
        }

        // 如果销售合同存在，将其转换为指定的VO对象，并返回成功结果
        return YResult.success(daoToInfoVO(bamuSaleContract));
    }


    /**
     * 保存或更新销售合同信息
     *
     * @param saveDto 包含要保存或更新的销售合同信息的数据传输对象
     * @return YResult<String> 包含操作结果和生成或更新的合同ID
     */
    @Override
    public YResult<String> saveInfo(SaleContractSaveDto saveDto) {
        try {
            // 检查输入参数是否为空
            if (saveDto == null) {
                throw new IllegalArgumentException("SaleContractSaveDto cannot be null");
            }

            // 初始化BamuSaleContract实体类
            BamuSaleContract bamuSaleContract = new BamuSaleContract();
            // 复制saveDto的属性到bamuSaleContract，排除特定属性
            BeanUtils.copyProperties(saveDto, bamuSaleContract);

            // 将签约日期和付款截止日期从字符串转换为Date类型
            bamuSaleContract.setSignDate(ConvertUtil.getString2Date(saveDto.getSignDate()));
            bamuSaleContract.setPaymentDeadlineDate(ConvertUtil.getString2Date(saveDto.getPaymentDeadlineDate()));

            // 处理特定的合同类型字段
            handleContractTypeSpecificFields(bamuSaleContract, saveDto);

            // 保存或更新销售合同信息
            ibamuSaleContractService.saveOrUpdate(bamuSaleContract);

            // 过审编辑或编辑时候 同步修改部分采购合同数据
            if (StringUtils.isNotEmpty(saveDto.getId())){
                BamuPurchaseContract purchaseContract = iBamuPurchaseContractService.getBySaleContractId(saveDto.getId());
                if (Objects.nonNull(purchaseContract)) {
                    updatePurseContractFielsdBySaleContract(bamuSaleContract, purchaseContract);
                    iBamuPurchaseContractService.saveOrUpdate(purchaseContract);
                }
            }

            // 更新主合同ID（如果有必要）
            updateMainContractIdIfNecessary(bamuSaleContract, saveDto);

            // 返回成功结果，包括生成或更新的合同ID
            return YResult.success(bamuSaleContract.getId());
        } catch (Exception e) {
            // 发生异常时，返回错误结果
            return YResult.error(ResultMsgEnum.SYS_ERROR);
        }
    }


    /**
     * 根据合同类型处理特定字段
     *
     * @param bamuSaleContract Bamu销售合同实体
     * @param saveDto          销售合同保存DTO
     */
    private void handleContractTypeSpecificFields(BamuSaleContract bamuSaleContract,
                                                  SaleContractSaveDto saveDto) {
        // 获取合同类型
        String contractType = saveDto.getContractType();

        // 如果是主合同，则处理主合同编号和名称
        if (StringUtils.equals(String.valueOf(SaleContractType.MASTER.getType()), contractType)) {
            // 如果合同编号不为空，则设置为主合同编号
            if (StringUtils.isNotBlank(saveDto.getContractNo())) {
                bamuSaleContract.setMainContractNo(saveDto.getContractNo());
            }
            // 如果合同名称不为空，则设置为主合同名称
            if (StringUtils.isNotBlank(saveDto.getContractName())) {
                bamuSaleContract.setMainContractName(saveDto.getContractName());
            }
        }
    }


    /**
     * 根据销售合同类型处理采购合同特定字段
     *
     * @param saleContract 销售合同dao
     * @param purchaseContract 采购合同dao
     */
    private void updatePurseContractFielsdBySaleContract(BamuSaleContract saleContract,
                                                  BamuPurchaseContract purchaseContract) {
        purchaseContract.setMainContractName(saleContract.getContractName());
        purchaseContract.setSaleContractNo(saleContract.getContractNo());
        purchaseContract.setSaleContractName(saleContract.getContractName());
        purchaseContract.setInquiryNo(saleContract.getInquiryNo());
        purchaseContract.setContractType(saleContract.getContractType());
        purchaseContract.setContractMethod(saleContract.getContractMethod());

        purchaseContract.setProjectId(saleContract.getProjectId());
        purchaseContract.setProjectName(saleContract.getProjectName());
        purchaseContract.setProjectAddress(saleContract.getProjectAddress());
        purchaseContract.setProjectDeptId(saleContract.getProjectDeptId());
        purchaseContract.setProjectDeptName(saleContract.getProjectDeptName());
        purchaseContract.setProjectManager(saleContract.getProjectManager());
        purchaseContract.setProjectManagerId(saleContract.getProjectManagerId());

        purchaseContract.setPurchasePersonId(saleContract.getPurchasePersonId());
        purchaseContract.setPurchasePersonName(saleContract.getPurchasePersonName());
        purchaseContract.setPurchasePhone(saleContract.getPurchasePhone());
        purchaseContract.setPurchaseDeptId(saleContract.getPurchaseDeptId());
        purchaseContract.setPurchaseDeptName(saleContract.getPurchaseDeptName());


    }


    /**
     * 如果必要，更新主合同ID
     * 如果是主合同且主合同ID为空，则更新主合同ID为当前合同ID
     *
     * @param bamuSaleContract 待更新的销售合同实体
     * @param saveDto 销售合同保存DTO，包含合同类型等信息
     */
    private void updateMainContractIdIfNecessary(BamuSaleContract bamuSaleContract,
                                                 SaleContractSaveDto saveDto) {
        // 获取合同类型
        String contractType = saveDto.getContractType();
        // 如果是主合同且主合同ID为空，则更新主合同ID为当前合同ID
        if (StringUtils.equals(String.valueOf(SaleContractType.MASTER.getType()), contractType)
                && StringUtils.isBlank(bamuSaleContract.getMainContractId())) {
            bamuSaleContract.setMainContractId(bamuSaleContract.getId());
            ibamuSaleContractService.updateById(bamuSaleContract);
        }
    }




    /**
     * 根据类型生成相应的编码
     *
     * @param type 编码的类型，用于区分不同种类的编码
     * @return 返回包含生成编码的YResult对象
     */
    @Override
    public YResult<String> generateCode(String type) {
        // 构造Redis中存储的key，包含前缀、短前缀、类型和当前日期
        String key = CODE_PREFIX + MINUS + SALE_CODE_PREFIX_SHORT + MINUS + type + MINUS + DateUtils.format(new Date(),
                "yyyyMMdd");
        redisCache.set(key, 0L, 24, TimeUnit.HOURS);
        // 递增key对应的值，用于生成编码的序列部分
        long incr = redisCache.incr(key);
        // 如果序列值大于9999，说明当天已生成较多编码，以8位格式化序列值
        if (incr > 9999) {
            return YResult.success(key + String.format("%08d", incr));
        }
        // 否则，以4位格式化序列值，用于生成编码
        return YResult.success(key + String.format("%04d", incr));
    }

    /**
     * 根据ID删除销售合同记录
     * 实际上是通过设置isDeleted字段来标记该记录为已删除，而不是物理删除
     *
     * @param id 销售合同的唯一标识
     * @return YResult对象，包含删除成功的信息或错误提示
     */
    @Override
    public YResult<String> deleted(String id) {
        try {
            // 根据ID查询销售合同是否存在
            BamuSaleContract bamuSaleContract = ibamuSaleContractService.getById(id);
            // 如果销售合同不存在，返回错误结果，提示没有数据
            if (Objects.isNull(bamuSaleContract)) {
                return YResult.error(ResultMsgEnum.NO_DATA);
            }
            // 创建一个新的销售合同对象，用于更新数据
            BamuSaleContract updateBamuSaleContract = new BamuSaleContract();
            // 设置要更新的销售合同的ID
            updateBamuSaleContract.setId(id);
            // 标记该销售合同为已删除状态
            updateBamuSaleContract.setIsDeleted(DataDeletedStatus.YES.getType());
            // 更新销售合同的记录
            ibamuSaleContractService.updateById(updateBamuSaleContract);
            // 返回成功结果，包含销售合同的ID
            return YResult.success(id);
        }catch (Exception e){
            log.error("删除销售合同失败",e);
            return YResult.error(ResultMsgEnum.SYS_ERROR);
        }

    }


    /**
 * 提交审批操作
 * 该方法接收一个审批数据传输对象（SaleContractSubmitApprovalDto），尝试提交销售合同的审批流程
 * 如果提交成功，返回一个成功结果，包含审批的ID；如果提交过程中发生异常，
 * 则返回一个错误结果，包含异常信息
 *
 * @param approvalDto 审批数据传输对象，包含审批所需的必要信息
 * @return YResult<String> 返回一个包含结果状态和审批ID的结果对象
 */
@Override
public YResult<String> submitApproval(SaleContractSubmitApprovalDto approvalDto) {
    try {
        // 调用处理类的submit方法，传入审批ID，执行审批提交操作
        saleContractAuditHandle.submit(approvalDto.getId());
        // 如果审批提交成功，返回成功结果，包含审批的ID
        return YResult.success(approvalDto.getId());
    } catch (Exception e) {
        log.error("提交审批异常", e);
        // 如果审批提交过程中发生异常，返回错误结果，包含异常信息
        return YResult.error(ResultMsgEnum.SUBMIT_APPROVAL_ERROR);
    }
}


    /**
     * 审批销售合同
     * 该方法接收一个销售合同审批数据传输对象，并尝试对其进行审批操作
     * 如果审批成功，返回一个表示成功的YResult对象，包含审批后的ID
     * 如果审批过程中出现异常，返回一个表示错误的YResult对象，包含错误信息
     *
     * @param approvalDto 销售合同审批Dto，包含审批所需信息
     * @return YResult对象，表示审批结果
     */
    @Override
    public YResult<String> approval(SaleContractApprovalDto approvalDto) {
        try {
            // 调用销售合同审批处理类的approval方法进行审批操作
            saleContractAuditHandle.approval(approvalDto);
            // 审批成功后，返回成功结果，携带审批后的ID
            return YResult.success(approvalDto.getId());
        } catch (Exception e) {
            log.error("审批销售合同失败", e);
            // 审批过程中发生异常，返回错误结果，携带异常信息
            return YResult.error(ResultMsgEnum.APPROVAL_ERROR);
        }
    }

    /**
     * 根据ID获取销售合同的采购信息
     *
     * @param id 销售合同的ID
     * @return 包含采购信息的YResult对象，或者错误/空的YResult对象
     */
    @Override
    public YResult<SaleContractPurchaseInfoVO> getSaleContractPurchaseInfo(String id) {
        // 检查输入的ID是否为空或空白，如果是，则返回参数错误的结果
        if (StringUtils.isBlank(id)) {
            return YResult.error(ResultMsgEnum.PARAM_ERROR);
        }

        // 根据销售合同ID获取采购合同信息，如果不存在，则返回成功但无内容的结果
        BamuPurchaseContract bamuPurchaseContract = iBamuPurchaseContractService.getBySaleContractId(id);
        if (Objects.isNull(bamuPurchaseContract)){
            return YResult.success();
        }

        // 如果存在采购合同，创建一个销售合同采购信息VO对象，并设置相关ID
        SaleContractPurchaseInfoVO infoVO = new SaleContractPurchaseInfoVO();
        infoVO.setSaleContractId(bamuPurchaseContract.getSaleContractId());
        infoVO.setPurchaseContractId(bamuPurchaseContract.getId());

        // 返回包含采购信息VO的成功结果
        return YResult.success(infoVO);
    }

    @Override
    public List<ContractMaterialExcelDto> exportMaterial(String contractId) {
        List<BamuContractMaterial> contractMaterialList  = iBamuContractMaterialService.listByContractId(contractId);
        if (CollectionUtils.isNotEmpty(contractMaterialList)){
            return contractMaterialList.stream().map(this::convertToExcelDto).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    /**
     * 将BamuContractMaterial转化成ContractMaterialExportDto
     */
    private ContractMaterialExcelDto convertToExcelDto(BamuContractMaterial material){
        ContractMaterialExcelDto dto = new ContractMaterialExcelDto();
        BeanUtils.copyProperties(material,dto);
        dto.setId(material.getId());
        return dto;
    }

    /**
     * 将数据库访问对象转换为视图对象
     * 此方法主要用于将数据库中的销售合同数据转换为前端展示的销售合同信息对象
     * 使用BeanUtils工具进行属性复制，简化了字段一一对应的过程
     *
     * @param bamuSaleContract 数据库中的销售合同对象
     * @return 返回转换后的销售合同信息VO对象
     */
    private SaleContractInfoVO daoToInfoVO(BamuSaleContract bamuSaleContract) {
        SaleContractInfoVO saleContractInfoVO = new SaleContractInfoVO();
        BeanUtils.copyProperties(bamuSaleContract, saleContractInfoVO);
        return saleContractInfoVO;
    }

    @Override
    public List<ContractExcelDto> export(SaleContractDto saleContractDto) {
        // 检查查询条件对象是否为空，如果为空则抛出异常
        if (saleContractDto == null) {
            throw new IllegalArgumentException("SaleContractDto cannot be null");
        }

        // 构建查询条件
        LambdaQueryWrapper<BamuSaleContract> queryWrapper =
                new LambdaQueryWrapper<BamuSaleContract>()
                        .eq(BamuSaleContract::getContractType, saleContractDto.getContractType())
                        .eq(BamuSaleContract::getIsDeleted, DataDeletedStatus.NO.getType())
                        .in(CollectionUtils.isNotEmpty(BaseContext.getProjectList()),BamuSaleContract::getProjectId, BaseContext.getProjectList())
                        .between(StringUtils.isNotBlank(saleContractDto.getBeginDate()) && StringUtils.isNotBlank(saleContractDto.getEndDate()),
                                BamuSaleContract::getSignDate,
                                ConvertUtil.getStartOfDay(safeConvertDate(saleContractDto.getBeginDate())), ConvertUtil.getEndOfDay(safeConvertDate(saleContractDto.getEndDate())))
                        .like(StringUtils.isNotBlank(saleContractDto.getContractNo()), BamuSaleContract::getContractNo, saleContractDto.getContractNo()).like(StringUtils.isNotBlank(saleContractDto.getContractName()), BamuSaleContract::getContractName, saleContractDto.getContractName()).eq(StringUtils.isNotBlank(saleContractDto.getProjectId()), BamuSaleContract::getProjectId, saleContractDto.getProjectId()).like(StringUtils.isNotBlank(saleContractDto.getProjectName()), BamuSaleContract::getProjectName, saleContractDto.getProjectName()).eq(StringUtils.isNotBlank(saleContractDto.getSupplierDeptId()), BamuSaleContract::getSupplierDeptId, saleContractDto.getSupplierDeptId()).like(StringUtils.isNotBlank(saleContractDto.getSupplierDeptName()), BamuSaleContract::getSupplierDeptName, saleContractDto.getSupplierDeptName()).eq(StringUtils.isNotBlank(saleContractDto.getPurchaseDeptId()), BamuSaleContract::getPurchaseDeptId, saleContractDto.getPurchaseDeptId()).like(StringUtils.isNotBlank(saleContractDto.getPurchaseDeptName()), BamuSaleContract::getPurchaseDeptName, saleContractDto.getPurchaseDeptName())
                        .like(StringUtils.isNotBlank(saleContractDto.getProjectDeptName()),
                                BamuSaleContract::getProjectDeptName,
                                saleContractDto.getProjectDeptName())
                        .like(StringUtils.isNotBlank(saleContractDto.getMainContractName()),
                                BamuSaleContract::getMainContractName,
                                saleContractDto.getMainContractName())
                        .like(StringUtils.isNotBlank(saleContractDto.getContractName()),
                                BamuSaleContract::getContractName,
                                saleContractDto.getContractName())
                        .eq(StringUtils.isNotBlank(saleContractDto.getAuditStatus()), BamuSaleContract::getAuditStatus, saleContractDto.getAuditStatus())
                        .eq(StringUtils.isNotBlank(saleContractDto.getBindContractStatus()),
                                BamuSaleContract::getBindContractStatus,
                                saleContractDto.getBindContractStatus())
                        .eq(StringUtils.isNotBlank(saleContractDto.getContractMethod()),
                                BamuSaleContract::getContractMethod,
                                saleContractDto.getContractMethod())
                        .orderByDesc(BamuSaleContract::getCreatedAt)
                        .orderByDesc(BamuSaleContract::getId);

        List<BamuSaleContract> contractMaterialList  = ibamuSaleContractService.list(queryWrapper);
        if (CollectionUtils.isNotEmpty(contractMaterialList)){
            return contractMaterialList.stream().map(this::convertToExcelDto).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }
    /**
     * 将BamuContractMaterial转化成ContractMaterialExportDto
     */
    private ContractExcelDto convertToExcelDto(BamuSaleContract bamuPurchaseContract){
        ContractExcelDto dto = new ContractExcelDto();
        BeanUtils.copyProperties(bamuPurchaseContract,dto);
        dto.setId(bamuPurchaseContract.getId());
        return dto;
    }
}
